﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Tool.hbm2ddl;

namespace YJKRevitBase.SqlUtility.ORMSuit
{
	public class ORMManger
	{
		public ORMManger(ConfigurationPacker inputConfiguartionPacker, List<Type> lstTypeNeedMap)
		{
			this.PrepareData(inputConfiguartionPacker, lstTypeNeedMap);
		}

		public ORMManger(ConfigurationPacker inputConfiguartionPacker)
		{
			Assembly callingAssembly = Assembly.GetCallingAssembly();
			Type useBaseType = typeof(BaseEntity);
			IEnumerable<Type> source = from n in callingAssembly.GetTypes()
			where useBaseType.IsAssignableFrom(n)
			select n;
			this.PrepareData(inputConfiguartionPacker, source.ToList<Type>());
		}

		private void PrepareData(ConfigurationPacker inputConfiguartionPacker, List<Type> lstTypeNeedMap)
		{
			this.m_hibernateConfig = new Configuration();
			this.m_useConfiguartionPacker = inputConfiguartionPacker;
			this.m_useAutoMappingHandler = new EntityAutoMappingHandler();
			Type baseType = typeof(BaseEntity);
			foreach (Type input in from n in lstTypeNeedMap
			where baseType.IsAssignableFrom(n)
			select n)
			{
				this.m_useAutoMappingHandler.RegiesType(input);
			}
			HbmMapping hbmMapping = this.m_useAutoMappingHandler.GetHbmMapping();
			this.m_useConfiguartionPacker.AddToNHibernateConfiguration(this.m_hibernateConfig);
			this.m_hibernateConfig.AddDeserializedMapping(hbmMapping, Guid.NewGuid().ToString());
			this.m_useSessionFactory = this.m_hibernateConfig.BuildSessionFactory();
		}

		~ORMManger()
		{
			if (this.m_currentSession != null)
			{
				this.CloseSession(false);
			}
			try
			{
				this.m_useSessionFactory.Close();
				this.m_useSessionFactory.Dispose();
				this.m_useSessionFactory = null;
			}
			catch (Exception)
			{
				this.m_useSessionFactory = null;
			}
		}

		public void OpenSession()
		{
			if (this.m_currentSession == null)
			{
				this.FinishTransaction(false);
				this.m_currentSession = this.m_useSessionFactory.OpenSession();
				this.m_useTransaction = this.m_currentSession.BeginTransaction();
			}
		}

		public void CloseSession(bool ifRollBack = false)
		{
			if (this.m_currentSession != null)
			{
				try
				{
					this.FinishTransaction(ifRollBack);
					this.m_currentSession.Close();
					this.m_currentSession.Dispose();
				}
				catch (Exception)
				{
				}
				finally
				{
					this.m_currentSession = null;
				}
			}
		}

		private void FinishTransaction(bool infRollBack = false)
		{
			if (this.m_useTransaction != null)
			{
				try
				{
					if (!infRollBack)
					{
						this.m_useTransaction.Commit();
					}
					else
					{
						this.m_useTransaction.Rollback();
					}
				}
				catch (Exception)
				{
					this.m_useTransaction.Rollback();
				}
				finally
				{
					this.m_useTransaction = null;
				}
			}
		}

		private void CreatSchema()
		{
			SchemaMetadataUpdater.QuoteTableAndColumns(this.m_hibernateConfig);
			new SchemaExport(this.m_hibernateConfig).Create(false, true);
		}

		private void DropSchema()
		{
			new SchemaExport(this.m_hibernateConfig).Drop(false, true);
		}

		public bool TryGetById<T>(int inputId, out T findedValue, bool ifMangeSession = true) where T : BaseEntity
		{
			findedValue = default(T);
			bool ifRollBack = false;
			bool result;
			try
			{
				if (ifMangeSession)
				{
					this.OpenSession();
				}
				findedValue = this.m_currentSession.Get<T>(inputId);
				result = true;
			}
			catch (Exception)
			{
				ifRollBack = true;
				result = false;
			}
			finally
			{
				if (ifMangeSession)
				{
					this.CloseSession(ifRollBack);
				}
			}
			return result;
		}

		public bool TryGetAll<T>(out List<T> finedValue, bool ifMangeSession = true) where T : BaseEntity
		{
			finedValue = null;
			bool ifRollBack = false;
			bool result;
			try
			{
				if (ifMangeSession)
				{
					this.OpenSession();
				}
				ICriteria criteria = this.m_currentSession.CreateCriteria(typeof(T)).SetCacheable(true);
				finedValue = criteria.List<T>().ToList<T>();
				result = true;
			}
			catch (Exception)
			{
				ifRollBack = true;
				result = false;
			}
			finally
			{
				if (ifMangeSession)
				{
					this.CloseSession(ifRollBack);
				}
			}
			return result;
		}

		public bool TryGetByFilter<T>(EntityFilterDel<T> useFilter, out List<T> finedValue, bool ifMangeSession = true) where T : BaseEntity
		{
			finedValue = null;
			bool ifRollBack = false;
			bool result;
			try
			{
				if (ifMangeSession)
				{
					this.OpenSession();
				}
				ICriteria criteria = this.m_currentSession.CreateCriteria(typeof(T)).SetCacheable(true);
				finedValue = (from n in criteria.List<T>()
				where useFilter(n)
				select n).ToList<T>();
				result = true;
			}
			catch (Exception)
			{
				ifRollBack = true;
				result = false;
			}
			finally
			{
				if (ifMangeSession)
				{
					this.CloseSession(ifRollBack);
				}
			}
			return result;
		}

		public bool TrySaveOrUpDate(BaseEntity inputEntity, bool ifMangeSession = true)
		{
			bool ifRollBack = false;
			bool result;
			try
			{
				if (ifMangeSession)
				{
					this.OpenSession();
				}
				this.m_currentSession.SaveOrUpdate(inputEntity);
				result = true;
			}
			catch (Exception)
			{
				ifRollBack = true;
				result = false;
			}
			finally
			{
				if (ifMangeSession)
				{
					this.CloseSession(ifRollBack);
				}
			}
			return result;
		}

		private bool TryUpDate(BaseEntity inputEntity, bool ifMangeSession = true)
		{
			bool ifRollBack = false;
			bool result;
			try
			{
				if (ifMangeSession)
				{
					this.OpenSession();
				}
				this.m_currentSession.Update(inputEntity);
				this.m_currentSession.Flush();
				result = true;
			}
			catch (Exception)
			{
				ifRollBack = true;
				result = false;
			}
			finally
			{
				if (ifMangeSession)
				{
					this.CloseSession(ifRollBack);
				}
			}
			return result;
		}

		private bool TrySave(BaseEntity inputEntity, bool ifMangeSession = true)
		{
			bool ifRollBack = false;
			bool result;
			try
			{
				if (ifMangeSession)
				{
					this.OpenSession();
				}
				this.m_currentSession.Save(inputEntity);
				this.m_currentSession.Flush();
				result = true;
			}
			catch (Exception)
			{
				ifRollBack = true;
				result = false;
			}
			finally
			{
				if (ifMangeSession)
				{
					this.CloseSession(ifRollBack);
				}
			}
			return result;
		}

		public bool TryDelete(BaseEntity inputEntity, bool ifMangeSession = true)
		{
			bool ifRollBack = false;
			bool result;
			try
			{
				if (ifMangeSession)
				{
					this.OpenSession();
				}
				this.m_currentSession.Delete(inputEntity);
				this.m_currentSession.Flush();
				result = true;
			}
			catch (Exception)
			{
				ifRollBack = true;
				result = false;
			}
			finally
			{
				if (ifMangeSession)
				{
					this.CloseSession(ifRollBack);
				}
			}
			return result;
		}

		private ConfigurationPacker m_useConfiguartionPacker;

		private EntityAutoMappingHandler m_useAutoMappingHandler;

		private Configuration m_hibernateConfig;

		private ISessionFactory m_useSessionFactory;

		private ISession m_currentSession;

		private ITransaction m_useTransaction;
	}
}
